package com.yjd.comm.encrypt;

import org.apache.commons.codec.binary.Base64;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.crypto.Cipher;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import java.io.UnsupportedEncodingException;
import java.util.*;

/**
 * AES加解密工具
 *
 * @author yanwe
 * createTime 2017-12-2017/12/29 9:27
 */
public class AesUtil {

    private static final Logger logger = LoggerFactory.getLogger(AesUtil.class);

    /**
     * AES CBC 加密
     * @param data 数据
     * @param aesKey AES密码(长度必须是16位的倍数)
     * @param iv 偏移量
     * @return Base64编码后的加密数据
     */
    public static String encryptByCBC(String data, String aesKey, String iv) {
        try {
            SecretKeySpec keySpec = new SecretKeySpec(aesKey.getBytes("UTF-8"), "AES");
            Cipher aesCipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
            aesCipher.init(Cipher.ENCRYPT_MODE, keySpec, new IvParameterSpec(iv.getBytes("UTF-8")));
            byte[] encrypted = aesCipher.doFinal(data.getBytes("UTF-8"));
            return Base64.encodeBase64String(encrypted);
        } catch (Exception e) {
            e.printStackTrace();
            logger.error(e.toString());
            return null;
        }
    }

    /**
     * AES CBC 解密
     *
     * @param data Base64编码后的加密数据
     * @param aesKey KEY
     * @param iv 偏移量
     * @return 原数据
     */
    public static String decryptByCBC(String data, String aesKey, String iv) {
        try {
            SecretKeySpec keySpec = new SecretKeySpec(aesKey.getBytes("UTF-8"), "AES");
            Cipher aesCipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
            aesCipher.init(Cipher.DECRYPT_MODE, keySpec, new IvParameterSpec(iv.getBytes("UTF-8")));
            byte[] encrypted = aesCipher.doFinal(Base64.decodeBase64(data));
            return new String(encrypted,"UTF-8");
        } catch (Exception e) {
            logger.error("数据[{}]解密失败，错误信息：{}", data, e.toString());
            return null;
        }
    }

    /**
     * AES ECB 加密
     *
     * @param data 数据
     * @param aesKey AES密码(长度必须是16位的倍数)
     * @return 加密后的数据
     */
    public static String encryptByECB(String data, String aesKey) {
        try {
            SecretKeySpec skeySpec = new SecretKeySpec(aesKey.getBytes(), "AES");
            Cipher aesCipher = Cipher.getInstance("AES/ECB/PKCS5Padding");
            aesCipher.init(Cipher.ENCRYPT_MODE, skeySpec);
            return Base64.encodeBase64String(aesCipher.doFinal(data.getBytes("UTF-8")));
        } catch (Exception e) {
            e.printStackTrace();
            logger.error(e.getMessage());
            return null;
        }
    }

    /**
     * AES ECB 解密
     *
     * @param data 数据
     * @param aesKey AES密码(长度必须是16位的倍数)
     * @return 解密后的数据
     */
    public static byte[] decryptByECB(String data, String aesKey) {
        try {
            SecretKeySpec skeySpec = new SecretKeySpec(aesKey.getBytes(), "AES");
            Cipher aesCipher = Cipher.getInstance("AES/ECB/PKCS5Padding");
            aesCipher.init(Cipher.DECRYPT_MODE, skeySpec);
            return aesCipher.doFinal(Base64.decodeBase64(data));
        } catch (Exception e) {
            e.printStackTrace();
            logger.error(e.getMessage());
            return null;
        }
    }

    public static void main(String[] args) throws UnsupportedEncodingException {
        String s = EncryptTool.generateRandom32();
        String s1 = EncryptTool.generateRandom16();


        Map result = new HashMap();
        result.put("order_id","RR2222");
        result.put("agent_order_id", "DD356666");
        result.put("remit_result","1");
        result.put("remit_time","20171101235901");
        result.put("code","");
        result.put("msg","");

        String s2 = sortMapByKey(result);

        String bytes = encryptByECB(s2, s);
        byte[] s3 = decryptByECB(bytes, s);
        System.out.println(s);
        System.out.println(s1);
        System.out.println(s2);

        System.out.println(new String(s3));
    }


    public static String sortMapByKey(Map<String, Object> map) {
        if (map == null || map.isEmpty()) {
            return null;
        }
        Map<String, Object> sortMap = new TreeMap<String, Object>(new MapKeyComparator());
        sortMap.putAll(map);
        StringBuffer strBuffer = new StringBuffer();
        int i =0;
        for(String key : sortMap.keySet()){
            if(i!=0){
                strBuffer.append("&");
            }
            strBuffer.append(key);
            strBuffer.append("=");
            strBuffer.append(sortMap.get(key));
            i++;
        }
        return strBuffer.toString();
    }

   static class MapKeyComparator implements Comparator<String> {
        @Override
        public int compare(String str1, String str2) {
            return str1.compareTo(str2);
        }
    }
}
